package com.autumn.chat.http;

import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.crypto.digest.HMac;
import cn.hutool.crypto.digest.HmacAlgorithm;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import com.autumn.chat.config.GlobalParam;
import com.autumn.chat.constant.BiLiBiLiConstant;

import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public abstract class BLiveHttpClient {

    /**
     * 获取公共的请求头
     * 参考 https://open-live.bilibili.com/document/doc&tool/auth.html#%E7%8E%AF%E5%A2%83%E5%9F%9F%E5%90%8D
     */
    public static JSONObject getCommonHeader(JSONObject requestBody) {

        JSONObject header = new JSONObject();
        // 接受的返回结果的类型。目前只支持JSON类型，取值：application/json。
        header.put("Accept" , "application/json");
        // 当前请求体（Request Body）的数据类型。目前只支持JSON类型，取值：application/json。
        header.put("Content-Type" , "application/json");

        // 使用requestBody计算md5值
        Digester md5 = new Digester(DigestAlgorithm.MD5);

        String md5Result = md5.digestHex(requestBody.toString());
        header.put("x-bili-content-md5" , md5Result);

        // unix时间戳，单位是秒。请求时间戳不能超过当前时间10分钟，否则请求会被丢弃。
        long unixTime = DateUtil.currentSeconds();
        header.put("x-bili-timestamp" , unixTime);

        // 签名方式。取值：HMAC-SHA256
        header.put("x-bili-signature-method" , "HMAC-SHA256");

        // 签名唯一随机数。用于防止网络重放攻击，建议您每一次请求都使用不同的随机数。
        int randomNum = 0;
        try {
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            randomNum = random.nextInt(1000);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        header.put("x-bili-signature-nonce" , String.valueOf(randomNum));

        header.put("x-bili-accesskeyid" , GlobalParam.ACCESS_KEY_ID);
        header.put("x-bili-signature-version" , "1.0");

        // 请求签名（注意生成的签名是小写的）。关于请求签名的计算方法，请参见签名机制
        // 拼接body
        String signStr = "x-bili-accesskeyid:"+ GlobalParam.ACCESS_KEY_ID + "\n" +
                "x-bili-content-md5:" + md5Result + "\n" +
                "x-bili-signature-method:HMAC-SHA256" + "\n" +
                "x-bili-signature-nonce:" + randomNum + "\n" +
                "x-bili-signature-version:1.0" + "\n" +
                "x-bili-timestamp:" + unixTime;
        // 使用secret秘钥 对文本进行sha256加密
        HMac hMac = new HMac(HmacAlgorithm.HmacSHA256,
                GlobalParam.ACCESS_KEY_SECRET.getBytes(StandardCharsets.UTF_8));
        String sign = hMac.digestHex(signStr.getBytes(StandardCharsets.UTF_8));
        header.put("Authorization" , sign);

        return header;
    }


    /**
     * 获得 HttpRequest
     * @param url 请求地址
     * @param requestBody 请求体
     * @return
     */
    public static HttpRequest getCommonHttpRequest(String url , JSONObject requestBody) {
        JSONObject commonHeader = getCommonHeader(requestBody);
        return HttpRequest.post(url)
                .header("Accept", (String) commonHeader.get("Accept"))
                .header("Content-Type", (String) commonHeader.get("Content-Type"))
                .header("x-bili-content-md5", (String) commonHeader.get("x-bili-content-md5"))
                .header("x-bili-timestamp", String.valueOf(commonHeader.get("x-bili-timestamp")))
                .header("x-bili-signature-method", (String) commonHeader.get("x-bili-signature-method"))
                .header("x-bili-signature-nonce", (String) commonHeader.get("x-bili-signature-nonce"))
                .header("x-bili-accesskeyid", (String) commonHeader.get("x-bili-accesskeyid"))
                .header("x-bili-signature-version", (String) commonHeader.get("x-bili-signature-version"))
                .header("Authorization", (String) commonHeader.get("Authorization"))
                .body(requestBody.toString());
    }
}
